#include "face_ota.h"
#include "face_ota_encrypt.h"

/* 调试打印接口 */
//#define FACE_OTA_DEBUG
#define FACE_OTA_LOG(format, ...)    printf("[face.c] " format, ##__VA_ARGS__)
#define __FACE_OTA_LOG(format, ...)  printf(format, ##__VA_ARGS__)
#define FACE_OTA_DEBUG_LOG(format, ...)    //printf(format, ##__VA_ARGS__)

#define VHW_PIN_FACE_POWER vPIN_C7          //人脸模组电源控制脚
#define VHW_UART_FACE vUART_3               

/* face power control */
#define FACE_MODULE_POWER_ON Device_Write(VHW_PIN_FACE_POWER, NULL, 0, 1)
#define FACE_MODULE_POWER_OFF Device_Write(VHW_PIN_FACE_POWER, NULL, 0, 0)

#define EVENT_FACE_OTA_RECV_MSG (0X00000001)		//处理人脸协议事件
#define EVENT_FACE_OTA_GET_STATUS (0x00000002)      //获取ota状态

#define EVENT_FACE_OTA_RESTART (0x00000008)		//OTA重启


#define PROTOCOL_STX 0xEFAA //帧数据头


#define PACK_TYPE_CONFRIM 0X00 //应答包类型：确认包
#define PACK_TYPE_ACK 0X01	   //应答包类型：应答包


/*M->H模组主动向主控发送的消息 note*/
#define FACE_NID_READY 0x00		        //模块已准备好
#define FACE_NID_FACE_STATE 0x01	    //算法执行成功，并且返回人脸信息 s_note_data_face
#define FACE_NID_UNKNOWNERROR 0x02      //未知错误
#define FACE_NID_OTA_DONE 0x03	        //OTA升级完毕
#define FACE_NID_EYE_STATE 0x04	        //解锁过程中睁闭眼状态

/*功能函数宏定义*/
#define CHECK_SUM_DATA_START 2          //校验和计算起始字节相对帧首字节偏移
#define CHECK_SUN_LEN_ADD 3	            //校验和计算长度相对帧长度增加的个数

#ifndef MAX_TX_PACKAGE_LEN
#define MAX_TX_PACKAGE_LEN            4196          //最大包长
#define RING_BUF_NUM 5
#else
#define RING_BUF_NUM 3
#endif

#define MAX_RX_PACKAGE_LEN            64          //最大包长

#define SEND_PACK_TIMEOUT           1000        //每包超时时间
#define POWER_ON_TIMEOUT            2500        //开机超时时间
#define FINISH_OTA_TIMEOUT          120000       //最后完成ota的时间

static RingBufferHandle_t uartFace_rbHandle = NULL;		//串口接收人脸模块的缓冲区句柄
static uint8_t encryptionFlag = 0;		   //加密模式   0：不加密     1：加密
static face_msg_otaheader_data otaHeaderData;           //ota固件信息
static face_msg_startota_data otaStartData;             //ota启动信息
static face_msg_otapacket_data *ota_data = NULL;
static uint32_t face_mtu = 0;                           //人脸ota包最大传输长度
static uint32_t otaPackSum = 0;                         //人脸ota包个数
static uint32_t otaCurrentPackPid = 0;                  //ota当前包
static uint8_t ota_ack_flag = 0;                        //ota包应答标志
static uint32_t ota_buffer_pos = 0;                     //ota缓存包位置
static uint32_t total_ota_len = 0;                      //ota包总大小
static uint32_t cur_ota_len = 0;                        //ota已完成长度


#pragma pack(1)
/*帧头数据结构*/
typedef struct
{
	uint16_t stx;  //帧头同步字
	uint8_t msgID; //消息ID
	uint16_t len;  //data数据长度
} ProtocolDataHead_stu_t;

/*加密帧头数据结构*/
typedef struct
{
	uint16_t stx;	//帧头同步字
	uint16_t len;	//data数据长度
	uint8_t data[]; //命令
} ProtocolDataHeadEncrypt_stu_t;

/*帧数据结构*/
typedef struct
{
	ProtocolDataHead_stu_t head; //帧头结构体
	uint8_t data[];				 //命令
} CmdPacket_stu_t;

/*M:模组
 *H:主控*/
/*M->H reply 模块对主控的应答data结构解析 msgID为0x00*/
typedef struct
{
	uint8_t r_msgID;  //应答对应的消息ID和命令的msg_ID 对应
	uint8_t result;	  //应答结果
	uint8_t r_data[]; //应答数据缓存
} Reply_data_stu_t;

typedef struct
{
	uint8_t n_msgID;  //note ID
	uint8_t n_data[]; //note 数据缓存
} Note_data_stu_t;

#pragma pack()

//发送包信息
static struct
{
	uint8_t dataBuf[MAX_TX_PACKAGE_LEN];      //当前发送的整包数据
	uint16_t dataLen;		//当前发送数据的总长度

	uint8_t cmd;			 //msgid
	uint8_t cnt;			 //
	FlagStatus waitAckFlag;	 //等待ack标志位
	uint32_t timeStamp;		 //时间戳
	uint32_t waitAckTimeout; //等待超时时间
	enum
	{					 
		TX_STA_IDLE,	  
		TX_STA_WAIT_ACK, 
        TX_STA_WAIT_NEXT
	} status;
} CmdPacketTxInfo;

//接收包信息
static struct
{
	uint8_t protocolBuf[MAX_RX_PACKAGE_LEN]; //协议buff
	uint8_t protocolCount;				  //协议计数

} CmdPacketRxInfo;


/**
  * @brief  校验和
  * @note
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 数据异或校验和:
  * 		非加密数据：除帧头（EF AA）和最后一个校验和以外的所有字节都需要计算
  * 		加密数据：除帧头（EF AA）、 长度（从0开始算，第2、3个字节）和最后一个校验和以外的所有字节都需要计算
  */
static uint8_t Face_CalcCheckSum(uint8_t *pData, uint16_t len)
{
	uint8_t sum = 0;
	for (; len; len--)
	{
		sum ^= *pData++;
	}
	return sum;
}

/**
  * @brief  人脸模组上电
  * @note
  */
static void FaceOTA_Module_Power_On(void)
{
	FACE_MODULE_POWER_ON;
    Device_Enable(VHW_UART_FACE);
	FACE_OTA_LOG("power on\r\n");
}

/**
  * @brief  人脸模组下电
  * @note
  */
static void FaceOTA_Module_Power_Down(void)
{
    FACE_MODULE_POWER_OFF;
}

static void FaceOTA_PrintfHexData(char *name, uint8_t *pData, uint16_t len)
{
    __FACE_OTA_LOG("%s(%d): ", name, len);
    for (int i = 0; i < len; i++)
    {
        __FACE_OTA_LOG("%02x ", pData[i]);
    }
    __FACE_OTA_LOG("\r\n\r\n");
}

/**
  * @brief  加载待发送的数据
  * @note   将要发出的数据，填入发送缓存区
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus FaceOTA_LoadingDataToBeSent(uint8_t *pData, uint16_t len)
{
	if (len > 0x7FFF) //直接发
	{
		len &= 0x7FFF;
		// FaceOTA_PrintfHexData("", pData, 10);
		Device_Write(VHW_UART_FACE, pData, len, 0);
		return SUCCESS;
	}
	return ERROR;
}

/**
  * @brief  人脸模块 数据打包
  * @note   
  *
  * @param  cmd：消息id
  * @param  pData：数据
  * @param  dataLen：数据长度
  * @param  waitAckFlag：等待回复标志
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus FaceOTA_SendPacket(uint8_t cmd, uint8_t *pData, uint16_t dataLen, FlagStatus waitAckFlag)
{
    CmdPacket_stu_t *pCmdPacket = (CmdPacket_stu_t *)CmdPacketTxInfo.dataBuf;
    ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)CmdPacketTxInfo.dataBuf; //加密模式帧头数据结构
	uint8_t encryptData[64] = {0};
	uint16_t encryptDataLen;
	uint16_t encryptInputLen;
    ErrorStatus re;

    //memset(&CmdPacketTxInfo,0,sizeof(CmdPacketTxInfo));
    CmdPacketTxInfo.cmd = cmd;
	CmdPacketTxInfo.waitAckFlag = waitAckFlag;
	CmdPacketTxInfo.cnt = 1;
	CmdPacketTxInfo.status = TX_STA_WAIT_ACK;
	CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();
    CmdPacketTxInfo.waitAckTimeout = SEND_PACK_TIMEOUT;

    //数据打包
    pCmdPacket->head.stx = PROTOCOL_STX;
	pCmdPacket->head.stx = FACEOTA_SWAP16(pCmdPacket->head.stx); //大小端转化
	pCmdPacket->head.msgID = cmd;
	pCmdPacket->head.len = dataLen;						 //data长度
	pCmdPacket->head.len = FACEOTA_SWAP16(pCmdPacket->head.len); //大小端转化
	memcpy(pCmdPacket->data, pData, dataLen);

    FACE_OTA_LOG("tx(%02X %d)\r\n", cmd, dataLen);

    pCmdPacket->data[dataLen] = Face_CalcCheckSum((uint8_t *)&(pCmdPacket->head.stx) + CHECK_SUM_DATA_START, dataLen + CHECK_SUN_LEN_ADD);
	CmdPacketTxInfo.dataLen = sizeof(CmdPacket_stu_t) + dataLen + 1;

    //开启OTA指令需要加密
    if(FaceOTAEncrypt_Get_EnFlag())
    {
        CmdPacketTxInfo.dataLen = dataLen + 5;
		// FaceOTA_PrintfHexData("encrypt packet", CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen); //仿真模式打印出加密前的数据
		pPacketHeadEncrypt->stx = PROTOCOL_STX;
		pPacketHeadEncrypt->stx = FACEOTA_SWAP16(pPacketHeadEncrypt->stx); //大小端转化
		encryptInputLen = dataLen + 3;      //数据内容 + msgid(1) + len(2)

        //数据加密
		FaceOTAEncrypt_SenseTime_Encrypt_Decrypt(1, (uint8_t *)&pCmdPacket->head.msgID, &encryptInputLen, encryptData, &encryptDataLen);

		memcpy(pPacketHeadEncrypt->data, encryptData, encryptDataLen);  //加密数据赋值
		pPacketHeadEncrypt->len = encryptDataLen;

		pPacketHeadEncrypt->data[encryptDataLen] = Face_CalcCheckSum((uint8_t *)pPacketHeadEncrypt->data, encryptDataLen);
		CmdPacketTxInfo.dataLen = sizeof(ProtocolDataHeadEncrypt_stu_t) + encryptDataLen + 1;
		pPacketHeadEncrypt->len = FACEOTA_SWAP16(pPacketHeadEncrypt->len); //大小端转化
    }

    //发送数据
    re = FaceOTA_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);
    FACE_OTA_LOG("tx end: %d\r\n", CmdPacketTxInfo.status);

    return re;
}

/**
  * @brief  发送固件信息
  * @note   
  *         
  * @param  
  */
static void FaceOTA_SendFwInfo(void)
{
    FaceOTA_SendPacket(FACE_MID_OTA_HEADER,&otaHeaderData,sizeof(face_msg_otaheader_data),RESET);
}

/**
  * @brief  人脸模组上电
  * @note
  */
static ErrorStatus FaceOTA_PowerOn(void)
{
	FaceOTA_Module_Power_On();
    return SUCCESS;
}

/**
  * @brief  wifi模组人脸OTA启动
  * @note   
  *         
  * @param  
  */
static ErrorStatus FaceOTA_Wifi_Module_Start(uint32_t file_len, uint32_t mtu)
{
    ota_ack_flag = 0;
    cur_ota_len = 0;
    ota_buffer_pos = 0;
    total_ota_len = file_len;
    face_mtu = mtu;
    otaCurrentPackPid = 0;
    return SUCCESS;
}

/**
  * @brief  人脸OTA启动
  * @note   
  *         
  * @param  
  */
static ErrorStatus FaceOTA_Start(uint32_t file_len, char *md5, uint32_t mtu)
{
    ota_ack_flag = 0;
    cur_ota_len = 0;
    ota_buffer_pos = 0;
    total_ota_len = file_len;
    face_mtu = mtu;
    otaCurrentPackPid = 0;

    // raw data size of single packet 分包的大小，最大不超过4KBytes
    uint16_t pkt_size = mtu;
    uint16_t num_pkt = ( file_len + pkt_size - 1 ) / pkt_size ;

    // 智能人脸模组OTA升级调试参考_20200426.pdf: 大端模式
    otaHeaderData.fsize_b[0] = file_len >> 24;
    otaHeaderData.fsize_b[1] = file_len >> 16;
    otaHeaderData.fsize_b[2] = file_len >> 8;
    otaHeaderData.fsize_b[3] = file_len >> 0;

    otaHeaderData.num_pkt[0] = num_pkt >> 24;
    otaHeaderData.num_pkt[1] = num_pkt >> 16;
    otaHeaderData.num_pkt[2] = num_pkt >> 8;
    otaHeaderData.num_pkt[3] = num_pkt >> 0;
    
    otaHeaderData.pkt_size[0] = pkt_size >> 8;
    otaHeaderData.pkt_size[1] = pkt_size >> 0;

    memcpy( otaHeaderData.md5_sum, md5, sizeof(otaHeaderData.md5_sum) );
    // MD5字符串必须小写
    for( uint32_t i=0; i<sizeof(otaHeaderData.md5_sum); i++ )
    {
        otaHeaderData.md5_sum[i] = tolower( otaHeaderData.md5_sum[i] );
    }  
    
    otaPackSum = otaHeaderData.num_pkt[0]*0x1000000 + otaHeaderData.num_pkt[1]*0x10000 + otaHeaderData.num_pkt[2]*0x100 + otaHeaderData.num_pkt[3];

    FaceOTA_Module_Power_On();
    FaceOTA_SendFwInfo();
    return SUCCESS;
}


// /**
//   * @brief  人脸OTA重新启动
//   * @note   
//   *         
//   * @param  
//   */
// static ErrorStatus FaceOTA_ReStart(face_msg_otaheader_data *headData)
// {
//     ota_ack_flag = 0;
//     memcpy(&otaHeaderData,headData,sizeof(face_msg_otaheader_data));
//     FaceOTA_Module_Power_Down();
//     OSAL_EventSingleCreate(COMP_FACE_OTA, EVENT_FACE_OTA_RESTART, 200, EVT_PRIORITY_MEDIUM);
//     return SUCCESS;
// }



/**
  * @brief  人脸OTA启动测试
  * @note   
  *         
  * @param  
  */
/*
static ErrorStatus FaceOTA_StartTest(void)
{
    //商汤7612ac0dcd68b256adabdc1f1b806d78
    uint8_t test_md5[32] = "7612ac0dcd68b256adabdc1f1b806d78";          //奥比5b9c435f7676d0361c6d4d998ff747ab
    
    //总包大小
    otaHeaderData.fsize_b[0] = 0;                   //商汤2c6542
    otaHeaderData.fsize_b[1] = 0x2c;                //奥比4e04a0
    otaHeaderData.fsize_b[2] = 0x65;            
    otaHeaderData.fsize_b[3] = 0x42;

    //分包数
    otaHeaderData.num_pkt[0] = 0x00;
    otaHeaderData.num_pkt[1] = 0x00;                //商汤03b4     3k大小
    otaHeaderData.num_pkt[2] = 0x02;                //奥比137e      1k     0681  3k
    otaHeaderData.num_pkt[3] = 0xc7;
    

    //分包大小
    otaHeaderData.pkt_size[0] = 0x10;
    otaHeaderData.pkt_size[1] = 0;

    memcpy(&otaHeaderData.md5_sum,test_md5,32);


    otaPackSum = otaHeaderData.num_pkt[0]*0x1000000 + otaHeaderData.num_pkt[1]*0x10000 + otaHeaderData.num_pkt[2]*0x100 + otaHeaderData.num_pkt[3];
    FACE_OTA_LOG(" otaPackSum %x\r\n",otaPackSum);
    
    FACE_OTA_LOG("\r\nfsizeb:");
    for(int i=0;i<4;i++)
    {
        FACE_OTA_LOG("%02x",otaHeaderData.fsize_b[i]);
    }
    FACE_OTA_LOG("\n");

    FACE_OTA_LOG("test md5:%s",otaHeaderData.md5_sum);

    FaceOTA_Module_Power_On();
    return SUCCESS;
}
*/

/**
  * @brief  修改波特率
  * @note   
  *         
  * @param  baud：波特率编号
  */
static void FaceOTA_Cfgbaudrate(uint8_t baud)
{
    face_msg_config_baudrate data;
    data.baudrate_index = baud;
    FaceOTA_SendPacket(FACE_MID_CONFIG_BAUDRATE,&data,sizeof(face_msg_config_baudrate),RESET);
}



/**
  * @brief  获取OTA状态
  * @note   
  *         
  * @param  
  */
static void FaceOTA_GetOTAStatus(void)
{
    uint8_t data[1];
    FaceOTA_SendPacket(FACE_MID_GET_OTA_STATUS,data,0,RESET);
}

/**
  * @brief  发送升级包
  * @note   给应用层调用API
  *         
  * @param  data:分包数据
  */
static void FaceOTA_RecvMsgProcess(void);
static ErrorStatus FaceOTA_SendUpgradePack(uint8_t *data, uint16_t len)
{
    if (len == 0)
    {
        return ERROR;
    }

    if (ota_data == NULL)
    {
        ota_data = OSAL_Malloc(sizeof(face_msg_otapacket_data) + face_mtu);
        if (ota_data == NULL)
        {
            return ERROR;
        }
    }

    memcpy(&ota_data->data[ota_buffer_pos], data, len);
    ota_buffer_pos += len;
    cur_ota_len += len;
    if (ota_buffer_pos < face_mtu && cur_ota_len < total_ota_len)
    {
        return SUCCESS;
    }

    uint32_t first_time = OSAL_GetTickCount();
    while (ota_ack_flag && ((OSAL_GetTickCount() - first_time) < 200))
    {
        FaceOTA_RecvMsgProcess();
    }

    FACE_OTA_LOG("ota pid: %ld, len: %ld\r\n", otaCurrentPackPid, ota_buffer_pos);

    ota_data->psize = FACEOTA_SWAP16(ota_buffer_pos);
    ota_data->pid = FACEOTA_SWAP16(otaCurrentPackPid);
    ErrorStatus ret = FaceOTA_SendPacket(FACE_MID_OTA_PACKET, ota_data, ota_buffer_pos + sizeof(face_msg_otapacket_data), RESET);
    otaCurrentPackPid++;
    ota_ack_flag = 1;
    ota_buffer_pos = 0;

    return ret;
}

/**
  * @brief  从底层环形缓存获取一包数据并解析
  *
  * @note   底层驱动收到数据，会暂存在环形缓存区
  *
  * @return 返回解析后的数据包地址，解析失败返回NULL
  */
static uint8_t *FaceOTA_GetOnePacket(void)
{
	static uint32_t idle_time = 0;
    uint8_t *protocolBuff = NULL;               //解析的buff
    uint8_t *pCnt = NULL;                       
	uint8_t sum = 0;
	uint16_t packetLen = 0;                     //整包长度
	uint8_t tmpData;                            //缓冲变量，从缓冲区读数据
	uint32_t tmpLen = 0;
    ProtocolDataHead_stu_t *pPacketHead = NULL;
    ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = NULL; //加密模式帧头数据结构

	uint8_t decryptData[MAX_RX_PACKAGE_LEN] = {0};
    uint8_t buff[64];
	uint16_t decryptDataLen;

    //查询缓冲区是否有数据
	tmpLen = OSAL_RingBufferGetValidSize(uartFace_rbHandle);
	if (tmpLen == 0)
	{
		/* 连续30ms没有读取到数据（30ms） */
		if (OSAL_GetTickCount() - idle_time > 30)
		{
			if(CmdPacketRxInfo.protocolCount)
			{
				FACE_OTA_DEBUG_LOG("face recv timeout\r\n");
			}
            idle_time = 0;
			CmdPacketRxInfo.protocolCount = 0; //清0解析计数
		}
		return NULL;
	}

    idle_time = OSAL_GetTickCount();

    FACE_OTA_DEBUG_LOG("face get pack len: %ld\r\n", tmpLen);
    pCnt = &(CmdPacketRxInfo.protocolCount);	//解析计数
    protocolBuff = CmdPacketRxInfo.protocolBuf; //解析缓存
    pPacketHead = (ProtocolDataHead_stu_t *)protocolBuff;
    pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)protocolBuff;
    //循环读字节
    for (; tmpLen; tmpLen--)
	{
		OSAL_RingBufferRead(uartFace_rbHandle, &tmpData); //读取到一个字节数据
        if(*pCnt == 0)
        {
            if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
            {
                protocolBuff[0] = tmpData;
                *pCnt = 1;
            }
        }
        else if(*pCnt == 1)
        {
            if (tmpData == (PROTOCOL_STX & 0x00FF)) //帧数据头低字节
			{
				protocolBuff[1] = tmpData;
				*pCnt = 2;
			}
            else if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
			{
            }
            else
            {
                *pCnt = 0;
            }
        }
        else if(*pCnt > 1)
        {
            protocolBuff[*pCnt] = tmpData;
            *pCnt = *pCnt + 1;

            if(FaceOTAEncrypt_Get_EnFlag() == 0) //非加密
            {
                if(*pCnt == 5)
                {
                    pPacketHead->len = FACEOTA_SWAP16(pPacketHead->len); //大小端转化
					pPacketHead->stx = FACEOTA_SWAP16(pPacketHead->stx); //大小端转化
                    FACE_OTA_LOG("rx len %04x, %04x\r\n", pPacketHead->len,pPacketHead->stx);
                }
                else if(*pCnt > 5)
                {
                    packetLen = pPacketHead->len + 6;  //包总长，data + 包头(2) + msgid(1) + datalen(2) + checksum(1)
                    if(packetLen == *pCnt)
                    {
                        sum = Face_CalcCheckSum(protocolBuff + CHECK_SUM_DATA_START, pPacketHead->len + CHECK_SUN_LEN_ADD);
                        if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
						{
                            FaceOTA_PrintfHexData("rx", protocolBuff, packetLen);
                            *pCnt = 0;
                            return protocolBuff;
                        }
                        else
                        {
                            FACE_OTA_LOG("CRC ERR\r\n");
                            // FaceOTA_PrintfHexData("CRC ERR", protocolBuff, packetLen);
                        }
                        
                        *pCnt = 0;
                        return NULL;
                        
                    }
                }
            }
            else //加密
            {
                if (*pCnt == 4)
				{
					pPacketHeadEncrypt->len = FACEOTA_SWAP16(pPacketHeadEncrypt->len); //大小端转化
					pPacketHeadEncrypt->stx = FACEOTA_SWAP16(pPacketHeadEncrypt->stx); //大小端转化
				}
				if (*pCnt > 4)
				{
					packetLen = pPacketHeadEncrypt->len + 5;
					if (*pCnt >= MAX_RX_PACKAGE_LEN || packetLen == *pCnt)
					{
						if (packetLen == *pCnt)
						{
							sum = Face_CalcCheckSum(pPacketHeadEncrypt->data, pPacketHeadEncrypt->len);
							if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
							{
								FaceOTAEncrypt_SenseTime_Encrypt_Decrypt(0, pPacketHeadEncrypt->data, &pPacketHeadEncrypt->len, decryptData, &decryptDataLen);
								memcpy(&pPacketHeadEncrypt->len, decryptData, decryptDataLen);
								pPacketHead->len = FACEOTA_SWAP16(pPacketHead->len); //大小端转化
                                FaceOTA_PrintfHexData("rx", protocolBuff, packetLen);
								*pCnt = 0;
								if ((pPacketHead->len + 6) <= MAX_RX_PACKAGE_LEN)
								{
									return protocolBuff;
								}
							}
						}
						*pCnt = 0;
						return NULL;
					}
				}
            }
        }
    }
	return NULL;
}


/**
  * @brief  发送设置加密模式给人脸模组
  * 
  * @param  seed :随机序列(4个字节)
  * @param  seedlen:随机数长度
  * @param  time :当前时间戳(4个字节)
  * @param  timelen :当前时间戳长度
  * 
  * @note
  *
  */
static void FaceOTA_SendEncryption(uint8_t *seed, uint8_t seedlen, uint8_t *time, uint8_t timelen)
{
    uint8_t databuf[64] = {0};
    uint8_t test_seed[4] = {0x57,0xDD,0x24,0xEE};
    face_msg_init_encryption_data *pdatabuf = (face_msg_init_encryption_data *)databuf;

    memcpy(pdatabuf->seed, seed, 4);

    memcpy(pdatabuf->crttime, time, 4);
    pdatabuf->mode = FACE_ENCMODE_AES; //AES加密模式 FACE_ENCMODE_DEFAULT FACE_ENCMODE_AES
    //FaceOTA_SendPacket(FACE_MID_INIT_ENCRYPTION,pdatabuf,sizeof(face_msg_init_encryption_data),RESET);
    //可以不发时间
    FaceOTA_SendPacket(FACE_MID_INIT_ENCRYPTION,pdatabuf,5,RESET);

}

/**
  * @brief  返回锁当前的时间戳
  *
  * @return 返回UTC时间（以 1970.1.1 00:00:00 为起始时间的秒计数）
  */
static uint32_t FaceOTA_GetUtcTimestamp(void)
{
	uint32_t timestamp = 1635764000;
	//OSAL_TimeGet(&timestamp, T_UTC);
	return timestamp;
}

/**
  * @brief  人脸模组初始化加密密钥处理函数
  *
  * @note
  */
static void FaceOTA_InitEncryption_Process(void)
{
	uint8_t seeddata[4] = {0};
	uint32_t timedata = 0;

	FaceOTAEncrypt_GenerateRandomNumber(seeddata); //获取随机数
	timedata = FaceOTA_GetUtcTimestamp();			//获取时间
	FaceOTA_SendEncryption(seeddata, 4, (uint8_t *)&timedata, 4);
	FaceOTAEncrypt_GenencKey(seeddata); //生成aes密钥
}


/**
  * @brief  处理读到的应答reply包结果
  * @note
  *
  * @param  pAckPacket：包内容
  */
static void FaceOTA_ReplyPacketResult(CmdPacket_stu_t *pAckPacket)
{
    FaceOTAMsg_t faceOtaMsg;
    Reply_data_stu_t *replyData = (Reply_data_stu_t *)pAckPacket->data;
    uint8_t databuf[1];

    if(replyData->result == FACE_MR_SUCCESS)
    {
        CmdPacketTxInfo.status = TX_STA_IDLE;
        switch(replyData->r_msgID)
        {
                //已发送加密序列号
            case FACE_MID_SET_DEBUG_ENC_KEY:
                //判断是否开启加密
                if(FaceOTAEncrypt_Get_EnFlag() != 1)
                {
                    //发送随机数
                    FaceOTA_InitEncryption_Process();   //启动加密处理并发送
                    FaceOTAEncrypt_Set_EnFlag(1);
                }
                break;

            //     //获取版本
            // case FACE_MID_GET_VERSION:
            //     FACE_OTA_LOG("version: %s\r\n", replyData->r_data);
            //     //启动OTA
            //     //FaceOTA_SendPacket(FACE_MID_START_OTA,&otaStartData,sizeof(face_msg_startota_data),RESET);
            //     FaceOTA_SendPacket(FACE_MID_START_OTA,databuf,0,RESET);
            //     FaceOTAEncrypt_Set_EnFlag(0);
            //     break;

                //已启动加密
            case FACE_MID_INIT_ENCRYPTION:
                FACE_OTA_DEBUG_LOG("encryption ready\r\n");
                otaStartData.v_primary = 2;
                otaStartData.v_secondary = 0;
                otaStartData.v_revision = 4;
                FaceOTA_SendPacket(FACE_MID_START_OTA,databuf,0,RESET);
                FaceOTAEncrypt_Set_EnFlag(0);
                // FaceOTA_SendPacket(FACE_MID_GET_VERSION,databuf,0,RESET); //获取版本
                
                break;

                //已开启OTA模式
            case FACE_MID_START_OTA: 
                FACE_OTA_DEBUG_LOG("start ota ready\r\n");
                FaceOTA_Cfgbaudrate(3);         //修改波特率
                break;

            case FACE_MID_STOP_OTA:
                break;

                //已设置波特率
            case FACE_MID_CONFIG_BAUDRATE:
                FACE_OTA_DEBUG_LOG("cfg baud ok\r\n");
                Device_SetUartBaudrate(VHW_UART_FACE, 460800);
                OSAL_EventSingleCreate(COMP_FACE_OTA, EVENT_FACE_OTA_GET_STATUS, 200, EVT_PRIORITY_MEDIUM);
                break;

                //已获取ota状态
            case FACE_MID_GET_OTA_STATUS:
                FACE_OTA_DEBUG_LOG("ota status: %d,pack_id:%02x%02x\r\n",replyData->r_data[0],replyData->r_data[1],replyData->r_data[2]);
                FaceOTA_SendFwInfo();   //发送固件包头
                break;
                 
                //OTA固件信息
            case FACE_MID_OTA_HEADER:
                faceOtaMsg.ota_result = FACE_OTA_READY;
                FACE_OTA_DEBUG_LOG("face ota ready\r\n");
                OSAL_MessagePublish(&faceOtaMsg,sizeof(faceOtaMsg));  //通知应用层OTA已准备就绪
                break;

                //OTA分包
            case FACE_MID_OTA_PACKET:
                FACE_OTA_LOG("face ota packet success\r\n");
                // faceOtaMsg.ota_result = FACE_OTA_READY;
                // OSAL_MessagePublish(&faceOtaMsg,sizeof(faceOtaMsg));  //通知应用层OTA已准备就绪
                ota_ack_flag = 0;
                if(otaCurrentPackPid == (otaPackSum - 1))
                {
                    CmdPacketTxInfo.status = TX_STA_WAIT_NEXT;
                    CmdPacketTxInfo.waitAckTimeout = FINISH_OTA_TIMEOUT;
                    CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();
                }
                
                break;
        }
        
    }
    else
    {
        FACE_OTA_LOG("reply error cmd: 0x%02x,result:%d\r\n",replyData->r_msgID,replyData->result);
        //重发
        CmdPacketTxInfo.cnt++;
        CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();
        FaceOTA_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);
    }

    
}

/**
  * @brief  处理note包的结果
  * @note   模块的状态包括：IDLE(0),BUSY(1),ERROR(2),INVALID(3) OTA进行中(4)
  *
  * @param  pAckPacket：包内容
  */
static void FaceOTA_NotePacketResult(CmdPacket_stu_t *pCmdPacket)
{
    FaceOTAMsg_t faceOtaMsg;
    static uint8_t m_relpy = 0;
    uint8_t databuf[64] = {0};
    Note_data_stu_t *noteData = (Note_data_stu_t *)pCmdPacket->data;
    
    //模块上电准备好了
    if(noteData->n_msgID == FACE_NID_READY && (m_relpy == 0))
    {
        CmdPacketTxInfo.status = TX_STA_IDLE;
        m_relpy = 1;
        //未产测发送加密debug序列号
        FaceOTA_SendPacket(FACE_MID_SET_DEBUG_ENC_KEY,(uint8_t *)&faceOTA_KeyIndex,sizeof(faceOTA_KeyIndex),RESET);
        //FaceOTA_SendPacket(FACE_MID_SET_RELEASE_ENC_KEY,(uint8_t *)&faceOTA_KeyIndex,sizeof(faceOTA_KeyIndex),RESET);

        // //已产测，直接发送随机数
        // FaceOTA_InitEncryption_Process();   //启动加密处理并发送
        // FaceOTAEncrypt_Set_EnFlag(1);
        
    }
    //OTA完成了
    else if(noteData->n_msgID == FACE_NID_OTA_DONE)
    {
        if(noteData->n_data[0] == 0)
        {
            faceOtaMsg.ota_result = FACE_OTA_SUCCESS;
        }
        else
        {
            faceOtaMsg.ota_result = FACE_OTA_ERROR;
        }
        CmdPacketTxInfo.status = TX_STA_IDLE;
        OSAL_MessagePublish(&faceOtaMsg,sizeof(faceOtaMsg));
    }
    
}

/**
  * @brief  人脸，解析读取包
  * @note
  *
  * @param  pData:数据包
  */
static void FaceOTA_ParseRxPacket(uint8_t *pData)
{
	CmdPacket_stu_t *pPacketHead = (CmdPacket_stu_t *)pData;

    FACE_OTA_LOG("rx: %02x\r\n", pPacketHead->data[0]);
    if (pPacketHead->head.msgID == FACE_MID_REPLY) //处理应答帧
    {
        FACE_OTA_DEBUG_LOG("reply pack\r\n");
        FaceOTA_ReplyPacketResult((CmdPacket_stu_t *)pData); 
    }

    else if (pPacketHead->head.msgID == FACE_MID_NOTE) //模块主动发给主控的信息
    {
        FACE_OTA_DEBUG_LOG("note pack\r\n");
        FaceOTA_NotePacketResult((CmdPacket_stu_t *)pData);
    }
}


/**
  * @brief  重发指令包
  *
  * @note   
  */
static void FaceOTA_ResendCmdPacket(void)
{
    FaceOTAMsg_t faceOtaMsg;
	uint32_t currentTime = OSAL_GetTickCount();
	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK) //当前状态正在等应答
	{
		if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.waitAckTimeout)
		{
			//ERR:超时
			FACE_OTA_LOG("wait ack Time out cmd = %#2x,%ld,%ld,%ld\r\n", CmdPacketTxInfo.cmd, currentTime, CmdPacketTxInfo.timeStamp, CmdPacketTxInfo.waitAckTimeout);
			
            if(CmdPacketTxInfo.cnt >= 3)
            {
                //重发一次后依然无回应，异常
                faceOtaMsg.ota_result = FACE_OTA_ERROR;
                CmdPacketTxInfo.status = TX_STA_IDLE;
                OSAL_MessagePublish(&faceOtaMsg,sizeof(faceOtaMsg));
            }
            else
            {
                //重新发送
                CmdPacketTxInfo.cnt++;
                CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();
                FaceOTA_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);
            }
            
		}

	}
    else if(CmdPacketTxInfo.status == TX_STA_WAIT_NEXT)
    {
        if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.waitAckTimeout)
		{
            FACE_OTA_LOG("wait next timeout\r\n");
            faceOtaMsg.ota_result = FACE_OTA_ERROR_TIMEOUT;
            CmdPacketTxInfo.status = TX_STA_IDLE;
            OSAL_MessagePublish(&faceOtaMsg,sizeof(faceOtaMsg));
        }
    }
}


/**
  * @brief  接收数据并解析处理
  *
  * @note   先接收数据再解析数据，如果接收到note包需要发送ack包
  */
static void FaceOTA_RecvMsgProcess(void)
{

	uint8_t *pData = NULL;
	pData = FaceOTA_GetOnePacket(); //得到一包数据并检验校验和
	
    if (pData != NULL)
	{
		FaceOTA_ParseRxPacket(pData); //解析数据
	}

	FaceOTA_ResendCmdPacket();		 //超时重发命令包
}



/**
  * @brief  人脸串口回调函数
  * @note   将串口底层读到的数据存入人脸读队列缓冲区
  *
  * @param  data:数据
  * @param  len:长度
  */
static void FaceOTA_ReceiveCb(VirtualHardware_enum_t dev,void *data, uint32_t len)
{
	if (uartFace_rbHandle == NULL)
	{
        FACE_OTA_DEBUG_LOG("uartFace_rbHandle == NULL\r\n");
		return;
	}
	for (uint32_t i = 0; i < len; i++)
	{
		uint8_t tmp = ((uint8_t *)data)[i];
        // printf("%02x ", tmp);
		if (OSAL_RingBufferWrite(uartFace_rbHandle, &tmp) != SUCCESS)
		{
			FACE_OTA_DEBUG_LOG("face ringbuff write err\r\n");
			return;
		}
	}
}


/**
  * @brief 人脸 创建串口读和写队列缓冲区
  *
  * @note 
  */
static void FaceOTA_CreateRingBuffHandle(void)
{
	static FlagStatus firstPowerOn = SET;
	if (firstPowerOn == SET)
	{
		if (uartFace_rbHandle == NULL)
		{
			uartFace_rbHandle = OSAL_RingBufferCreate(500, 1);	//创建接收人脸模组的缓冲区
        }
		firstPowerOn = RESET;
	}
}



/**
  * @brief 创建周期事件
  * 
  * @note  
  */
static void FaceOTA_Create_Repeat_Event(void)
{
	/* 创建定时处理人脸协议 */
	OSAL_EventRepeatCreate(COMP_FACE_OTA, EVENT_FACE_OTA_RECV_MSG, 10, EVT_PRIORITY_MEDIUM);
}



static uint32_t Face_OTA_Task(uint32_t event)
{
    /* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
        FaceOTA_CreateRingBuffHandle();
        Device_RegisteredCB(VHW_UART_FACE, FaceOTA_ReceiveCb);
        FaceOTA_Create_Repeat_Event();
        CmdPacketTxInfo.status = TX_STA_WAIT_NEXT;
        CmdPacketTxInfo.waitAckTimeout = POWER_ON_TIMEOUT;
        CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();
        memset(CmdPacketRxInfo.protocolBuf, 0, sizeof(CmdPacketRxInfo.protocolBuf));

        SYS_API(FaceOTA_PowerOn);
        SYS_API(FaceOTA_Start);
        SYS_API(FaceOTA_SendUpgradePack);
        SYS_API(FaceOTA_Wifi_Module_Start);
        // SYS_API(FaceOTA_ReStart);
        //SYS_API(FaceOTA_StartTest);

        return ( event ^ EVENT_SYS_START );
    }

    /* 接收人脸模组消息并处理*/
	if (event & EVENT_FACE_OTA_RECV_MSG)
	{
		FaceOTA_RecvMsgProcess();
		return (event ^ EVENT_FACE_OTA_RECV_MSG);
	}

    /* 获取ota状态*/
	if (event & EVENT_FACE_OTA_GET_STATUS)
	{      
		FaceOTA_GetOTAStatus();
		return (event ^ EVENT_FACE_OTA_GET_STATUS);
	}

    // /* ota重启 */
	// if (event & EVENT_FACE_OTA_RESTART)
	// {
	// 	FaceOTA_Module_Power_On();
	// 	return (event ^ EVENT_FACE_OTA_RESTART);
	// }

    return 0;
}
COMPONENT_TASK_EXPORT(COMP_FACE_OTA, Face_OTA_Task, 0);

char import_kos_face_ota;
